#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QCryptographicHash>
#include <QObject>
#include <rsa.h>
#include <aes.h>
#include <QDir>
#include <QDebug>
#include <string.h>
#include <iostream>
#include <aes_gcm.h>
#include <QPixmap>
#include <QPalette>
#include <QBitmap>
#include "diffie_hellman.h"
QString username;
QString password;
int usernum;

void MainWindow::setip(char *argipa[])
{
    QString str = QString(QLatin1String(argipa[1]));
    ui->lineIP->setText(str);
    str = QString(QLatin1String(argipa[2]));
    ui->lineport->setText(str);
}

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    mainui_1= new mainui;
    mainui_1->tcpClient=new QTcpSocket(this);
    ui->setupUi(this);
    //需要连接服务器之后再进行登录认证
    ui->pushButton->setEnabled(true);
    ui->pushButton->setEnabled(false);
    ui->lineIP->setText("127.0.0.1");
    ui->lineport->setText("5000");

    mainui_1->DH.DH_Initialize(); //生成g,p,KA

    /*
     * 设置背景图片
     */
     QPixmap bgImages(":/beijingtupian/juzi.jpeg");
     QPalette bgPalette = this->palette();
     bgPalette.setBrush(QPalette::Background,bgImages);
     this->setPalette(bgPalette);
     setMask(bgImages.mask());// set background mask attribute same as background's image

//    unsigned char gcm_key[] = {//aes 256位密钥,char[] 数组
//            0xee,0xbc,0x1f,0x57,0x48,0x7f,0x51,0x92,0x1c,0x04,0x65,0x66,
//            0x5f,0x8a,0xe6,0xd1,0x65,0x8b,0xb2,0x6d,0xe6,0xf8,0xa0,0x69,
//            0xa3,0x52,0x02,0x93,0xa5,0x72,0x07,0x8f};
//    unsigned char gcm_pt[] = {//明文
//            0xf5,0x6e,0x87,0x05,0x5b,0xc3,0x2d,0x0e,0xeb,0x31,0xb2,0xea,
//            0xcc,0x2b,0xf2,0xb4
//    };
//    unsigned char gcm_ct[] = {//密文
//            0xf7,0x26,0x44,0x13,0xa8,0x4c,0x0e,0x7c,0xd5,0x36,0x86,0x7e,
//            0xb9,0xf2,0x17,0x27
//    };
//    qDebug()<<"size:"<<sizeof(gcm_key);
//    aes_gcm A(A.getgcmchar(gcm_key,sizeof(gcm_key)));
//    A.gcm_pt_len=sizeof(gcm_pt);
//    A.gcm_ct_len=sizeof(gcm_ct);
//    A.gcm_pt=A.getgcmchar(gcm_pt,sizeof(gcm_pt));
//    A.gcm_ct=A.getgcmchar(gcm_ct,sizeof(gcm_ct));
//    A.aes_gcm_encrypt();
//   .aes_gcm_decrypt();
//    A.aes_encrypt();
//    A.aes_decrypt();
//    qDebug()<<"rslt:"<<A.output2;
//    diffie_hellman DH;
//    DH.DH_Initialize();
//    DH.server_get_key();
//    DH.client_get_key();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()//登录操作，发送登录请求
{
    QString msg,msg0,msg1;
    //发送request请求
    //判断收到的回应来确定是否能够通过
    //通过则跳转界面
    username=ui->lineEdit->text();
    password=ui->lineEdit_2->text(); 
    //对RSA对象初始化
    //    mainui_1->rsa_a.RSA_Initialize();
        mainui_1->rsa_a.n=3425801;
        mainui_1->rsa_a.e=5327;
        mainui_1->rsa_a.d=1458263;
    //发送登录消息，包含rsa a公钥e和n，包含DH算法生成的g，p，KA
    //使用预共享密钥加密msg request-后面的部分

    //预共享密钥
    QByteArray psk_key0="5vJRIt+Aigc0nt+xClI/kV5i2e2ltOhJC/rQvpDmlRA=";
    QByteArray psk_key1=QByteArray::fromBase64(psk_key0);
    mainui_1->psk_key=new unsigned char[32];
    int i;
    for(i=0;i<32;i++){
        mainui_1->psk_key[i]=(unsigned char)psk_key1[i];//其实有格式问题
    }

    msg0="request-";
    msg1=username+"-"+MD5encryption(password)+"-"+QString::number(mainui_1->rsa_a.e)+"-"+QString::number(mainui_1->rsa_a.n)+"-"+QString::number(mainui_1->DH.g)+"-"+QString::number(mainui_1->DH.p)+"-"+QString::number(mainui_1->DH.KA)+"-1-";//需要操作，服务器接收到登录请求后提取用户名和密码
    //msg="request-"+username+"-"+MD5encryption(password)+"-"+QString::number(mainui_1->rsa_a.e)+"-"+QString::number(mainui_1->rsa_a.n)+"-"+QString::number(mainui_1->DH.g)+"-"+QString::number(mainui_1->DH.p)+"-"+QString::number(mainui_1->DH.KA);//需要操作，服务器接收到登录请求后提取用户名和密码
    aes_gcm aesg(aesg.getgcmchar(mainui_1->psk_key,32));
    aesg.input1=msg1;
    QByteArray rslt;
    aesg.aes_encrypt();
    rslt=msg0.toUtf8()+aesg.output1;
    int l=rslt.length();
    qDebug()<<"msg length"<<l;
    mainui_1->tcpClient->write(rslt.toBase64());//发送的登录请求，格式是request-用户名-密码hash值-客户端rsa公钥e-客户端rsa公钥n-g-p-KA
}

void MainWindow::on_pushButton_2_clicked()//连接服务器，需要先连接服务器
{
    if(ui->pushButton_2->text()=="建立连接"){
    ui->pushButton_2->setEnabled(false);
    dis=QObject::connect(mainui_1->tcpClient, &QTcpSocket::readyRead, this, &MainWindow::ReadData);//建立连接时，绑定接收信号的槽函数是readdata
    QString address;
    address=ui->lineIP->text();
    int port;
    port=ui->lineport->text().toInt();
    mainui_1->tcpClient->connectToHost(address,port);//连接
    //等待连接成功
    if(!mainui_1->tcpClient->waitForConnected(30000))
    {
       qDebug() << "Connection failed!";
       ui->state->setText("连接失败，点击重连");
       return;
    }
    //连接成功
    qDebug() << "Connect successfully!";
    ui->state->setText("连接成功");
    ui->pushButton->setEnabled(true);//允许发送登录消息
    ui->pushButton_2->setText("关闭连接");
    return;
    }
    if(ui->pushButton_2->text()=="关闭连接"){
    mainui_1->tcpClient->disconnectFromHost();
    ui->pushButton_2->setText("建立连接");
    ui->state->setText("等待连接");
    ui->pushButton->setEnabled(false);
    return;
    }
}
void MainWindow::ReadData()
{
    //接收服务器的回应，允许登陆则跳转界面
    //设计服务器的确认消息有三种
    //允许登录消息，同时对于已经登录了的客户端是列表更新消息，ok-服务器rsa.e-rsa.n-当前用户人数（加上了这个新登录的）-用户名1-用户名2-...
    //错误提示信息，error-1- 表示在服务器的用户表中没有相应的用户名或密码的hash值不正确
    //error-2- 表示该用户已经登录了，不能重复登录
    QByteArray buffer;
        //读取缓冲区数据
    buffer = QByteArray::fromBase64(mainui_1->tcpClient->readAll());
    QString s;
    s=QString::fromUtf8(buffer);
    //qDebug()<<"s:"<<s;
    QStringList l;
    l=s.split("-");
    if(l.at(0)=="error"){
        if(l.at(1)=="1"){
        qDebug()<<"input error";
        ui->label_3->setText("服务器提示错误，请重新输入");
         QMessageBox::information(0,"infor","用户名或密码错误！");
        return;}
        else if(l.at(1)=="2"){
            qDebug()<<"repeat error";
            ui->label_3->setText("账号已经登录了，换一个");
            QMessageBox::information(0,"infor","已经登录了");
            return;
        }
    }
    if(s.startsWith(("ok-"))){//通过登录确认消息，获取服务器的公钥和n,获取当期人数和用户列表,获取KB，K
        QStringList list;
        list=s.split("-");
        int i=0;
        int l;
        QString tmp;
        list=s.split("-");
        qDebug()<<"list.at0"<<list.at(0);
        if(list.at(0)=="ok"){
            tmp=list.at(1);
            mainui_1->rsa_b.e=tmp.toInt();
            tmp=list.at(2);
            mainui_1->rsa_b.n=tmp.toInt();
            //DH Key
            QString dfkey=list.at(3);
            mainui_1->DH.KB=dfkey.toInt();
            mainui_1->DH.client_get_key();

            tmp=list.at(4);
            usernum=tmp.toInt();
            l=tmp.toInt();
            qDebug()<<"l:"<<l;
            usernum=l;
            for(i=5;i<5+l;i++){
                mainui_1->usernamelist.append(list.at(i));
            }
        qDebug()<<"length"<<tmp.toInt();
        connect(mainui_1,SIGNAL(sendsignal_1()),this,SLOT(show1()));//当退出子界面时，调用主界面的show()函数
        disconnect(dis);//退出主界面时，需要断开当前有数据可接受的信号和readdata槽函数的联系，为了在子界面mainui中绑定子界面的接收数据函数。
        mainui_1->Initialize();//调用子界面的初始化函数
        this->hide();
        mainui_1->show();
        }

    }
}
QString MainWindow::MD5encryption(QString s)
{
    QString rslt;
    rslt=QCryptographicHash::hash(s.toLatin1(),QCryptographicHash::Md5).toHex();
    return rslt;
}
void MainWindow::show1()//从mianui界面返回到登录界面调用
{
    mainui_1->tcpClient->abort();
    mainui_1->tcpClient=new QTcpSocket(this);
    mainui_1->usernamelist.clear();
    usernum=0;
    ui->pushButton_2->setText("建立连接");
    ui->pushButton_2->setEnabled(true);
    ui->state->setText("等待连接");
    ui->lineEdit->clear();
    ui->lineEdit_2->clear();
    show();
}
